package org.xm.sk.controller.dbase;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.core.io.Resource;
import org.springframework.data.domain.Page;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestOperations;
import org.xm.sk.common.JacksonUtil;
import org.xm.sk.common.ToolsUtil;
import org.xm.sk.exception.DataNotFoundException;
import org.xm.sk.exception.RequestParamterException;
import org.xm.sk.module.IdBitWorker;
import org.xm.sk.service.data.BaseService;
import org.xm.sk.service.security.XmUser;
import org.xm.sk.vo.Base;
import org.xm.sk.vo.ob.Ids;
import org.xm.sk.vo.ob.MapList;
import org.xm.sk.vo.ob.PageConf;
import org.xm.sk.vo.ob.ResultMsg;
import org.xm.sk.vo.ob.UserInfo;
import org.xm.sk.vo.ob.WxEncData;
import org.xm.sk.vo.ob.WxUserInfo;
import org.xm.sk.vo.tb.Image;
import org.xm.sk.vo.tb.Organ;
import org.xm.sk.vo.tb.Role;
import org.xm.sk.vo.tb.Shop;
import org.xm.sk.vo.tb.User;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import springfox.documentation.annotations.ApiIgnore;

@SuppressWarnings("unchecked")
@Api(tags = { "user" })
@Slf4j
@RestController
@RequestMapping(value="/users")
public class UserController {
    
    @Autowired
    private MessageSource messages;
    @Autowired
    private BaseService<User> userService;
    @Autowired
    private BaseService<Shop> shopService;
    @Autowired
    private BaseService<Role> roleService;
    @Autowired
    private BaseService<Image> imageService;
    @Autowired
    private RestOperations restOperations;
    @Autowired
    private IdBitWorker idBitWorker;
    
    @ApiOperation(value="创建用户", notes="根据user对象创建用户，使用此接口需要ADMIN权限")
    @ApiImplicitParam(name = "user", value = "用户详细实体user", required = true, dataType = "User")
    @PreAuthorize("hasRole('ADMIN')")
    @RequestMapping(value="", method=RequestMethod.POST)
    public ResultMsg add(@RequestBody User user) throws Exception {
        User u = null;
        if (null == user.getId() || 1 > user.getId()) {
            u = new User();
        } else {
            u = (User) userService.findById(user.getId());
            if (!Base.isValid(u))
                u = new User();
        }
        u.getShops().clear();
        if (null != user.getShopId()
                && 0 < user.getShopId()) {
            Shop shop = (Shop) shopService
                    .findById(user.getShopId());
            if (Base.isValid(shop))
                u.getShops().add(shop);
        }
        u.getRoles().clear();
        if (null != user.getRoleIds() && !user.getRoleIds().isEmpty()) {
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("findByIdIn", user.getRoleIds());
            Set<Role> roles = (Set<Role>) roleService.findAllByPage(null, map);
            if (null != roles && !roles.isEmpty()) {
                u.getRoles().addAll(roles);
            }
        }
        u.setImage(null);
        if (null != user.getImageId() && 0 < user.getImageId()) {
            Image image = (Image) imageService.findById(user.getImageId());
            if (Base.isValid(image))
                u.setImage(image);
        }
        u.setName(user.getName());
        u.setNickname(user.getNickname());
        u.setPhone(user.getPhone());
        if (null != user.getPsw() && 0 < user.getPsw().trim().length())
            u.setPsw(ToolsUtil.desdecrypt(user.getPsw()));
        if (null == u.getId()) {
            u.setCode(idBitWorker.nextUserNum());
            userService.add(u);
        } else {
            userService.update(u);
        }
        return new ResultMsg("200", messages.getMessage("success", null, "SUCCESS", null), new Date());
    }

    @ApiIgnore()
    @ApiOperation(value="删除用户", notes="根据URI的id来指定删除对象")
    @ApiImplicitParam(name = "id", value = "用户ID", required = true, paramType = "path", dataType = "int")
    @RequestMapping(value="/{id}", method=RequestMethod.DELETE)
    public ResultMsg delete(@PathVariable Integer id) {
        userService.delete(id);
        return new ResultMsg("200", messages.getMessage("success", null, "SUCCESS", null), new Date());
    }
    
    @ApiOperation(value="删除用户", notes="根据POST的id列表来指定删除对象，可批量")
    @ApiImplicitParam(name = "ids", value = "用户ID集", required = true, dataType = "Ids")
    @RequestMapping(value="/delete", method=RequestMethod.DELETE)
    public ResultMsg Batchdelete(@RequestBody Ids ids) {
        userService.delete(ids.getIds());
        return new ResultMsg("200", messages.getMessage("success", null, "SUCCESS", null), new Date());
    }
    
    @ApiOperation(value="更新用户详细信息", notes="根据URI的id来指定更新对象，并根据传过来的user信息来更新用户详细信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "用户ID", required = true, paramType = "path", dataType = "int"),
            @ApiImplicitParam(name = "user", value = "待更新的用户详细实体user", required = true, dataType = "User")
    })
    @RequestMapping(value="/{id}", method=RequestMethod.PUT)
    public ResultMsg update(@PathVariable Integer id, @RequestBody User user) throws DataNotFoundException {
        User u = (User) userService.findById(id);
        if (null == u) {
            throw new DataNotFoundException(User.class.getName());
        }
        user.setId(id);
        userService.update(user);
        return new ResultMsg("200", messages.getMessage("success", null, "SUCCESS", null), new Date());
    }

    @ApiOperation(value="获取用户详细信息", notes="根据URI的id来获取用户详细信息")
    @ApiImplicitParam(name = "id", value = "用户ID", required = true, paramType = "path", dataType = "int")
    @RequestMapping(value="/{id}", method=RequestMethod.GET)
    public User load(@PathVariable Integer id) throws DataNotFoundException {
        User u = (User) userService.findById(id);
        if (null == u) {
            throw new DataNotFoundException(User.class.getName());
        }
        return u;
    }
    
    @ApiOperation(value="获取用户列表", notes="根据提交的分页信息列出所以用户信息")
    @ApiImplicitParam(name = "pageConf", value = "分页信息实体", required = true, dataType = "PageConf")
    @RequestMapping(value={"/list"}, method=RequestMethod.POST)
    public MapList<User> list(@RequestBody PageConf pageConf) {
        List<User> u = null;
        Long allCount = null;
        Object o = userService.findAllByPage(pageConf);
        if (o instanceof Page) {
            allCount = ((Page<User>) o).getTotalElements();
            u = ((Page<User>) o).getContent();
        } else {
            allCount = (long) ((List<User>) o).size();
            u = (List<User>) o;
        }
        for (User c : u) {
            if (null != c.getShops() && !c.getShops().isEmpty()) {
                for (Shop s : c.getShops()) {
                    if (Base.isValid(s)) {
                        c.setShopName(s.getName());
                        break;
                    }
                }
            }
            c.getRoleIds().clear();
            if (null != c.getRoles() && !c.getRoles().isEmpty()) {
                String roleNames = "";
                for (Role r : c.getRoles()) {
                    roleNames += "," + r.getDame();
                    c.getRoleIds().add(r.getId());
                }
                if (0 < roleNames.length()) {
                    roleNames = roleNames.substring(1);
                    c.setRoleNames(roleNames);
                }
            }
            if (Base.isValid(c.getImage()))
                    c.setImageId(c.getImage().getId());
        }
        return new MapList<User>(allCount, u);
    }

    // --------------------- 业务具体接口 ---------------------
    
    @ApiOperation(value = "获取用户详细信息", notes = "获取已登录的自己的用户详细信息")
    @RequestMapping(value = "", method = RequestMethod.GET)
    public UserInfo loadSelf() throws DataNotFoundException {
        XmUser xmUser = (XmUser) SecurityContextHolder.getContext()
                .getAuthentication().getPrincipal();
        User u = (User) userService.findById(xmUser.getUserid());
        if (null == u) {
            throw new DataNotFoundException(User.class.getName());
        }
        UserInfo ui = new UserInfo(u.getId(), null != u.getImage() ? u.getImage().getId() : null, u.getName(),
                u.getNickname(), u.getCreatedate(), u.getOrgan().getId(),
                u.getOrgan().getName(), null, null);
        Map<Integer, String> allotName = new HashMap<Integer, String>();
        for (Organ organ : u.getAllot_organs()) {
            allotName.put(organ.getId(), organ.getName());
        }
        ui.setAllotName(allotName);
        Map<Integer, String> roleAlias = new HashMap<Integer, String>();
        for (Role role : u.getRoles()) {
            roleAlias.put(role.getId(), role.getDame());
        }
        ui.setRoleAlias(roleAlias);
        return ui;
    }

    @ApiOperation(value = "微信用户信息补充", notes = "提交微信用户信息进行系统用户信息补充，可补充手机号信息")
    @ApiImplicitParam(name = "wxUserInfo", value = "微信用户补充信息实体", required = true, dataType = "WxUserInfo")
    @RequestMapping(value = "/wx", method = RequestMethod.POST)
    public ResultMsg supplement(@RequestBody WxUserInfo wxUserInfo) throws Exception {
        XmUser xmUser = (XmUser) SecurityContextHolder.getContext()
                .getAuthentication().getPrincipal();
        User u = (User) userService.findById(xmUser.getUserid());
        if (null == u) {
            throw new DataNotFoundException(User.class.getName());
        }
        if (null != wxUserInfo.getImageUrl() && 0 < wxUserInfo.getImageUrl().trim().length()) {
            HttpHeaders headers = new HttpHeaders();
            HttpEntity<Resource> httpEntity = new HttpEntity<Resource>(headers);
            ResponseEntity<byte[]> response = restOperations.exchange(wxUserInfo.getImageUrl().trim(), HttpMethod.GET,
                    httpEntity, byte[].class);
            Image image = new Image();
            image.setName(u.getName());
            image.setFile(response.getBody());
            u.setImage(image);
        }
        if (null != wxUserInfo.getNickname() && 0 < wxUserInfo.getNickname().trim().length())
            u.setNickname(wxUserInfo.getNickname());
        if (null != wxUserInfo.getCity() && 0 < wxUserInfo.getCity().trim().length())
            u.setCity(wxUserInfo.getCity());
        if (null != wxUserInfo.getProvince() && 0 < wxUserInfo.getProvince().trim().length())
            u.setProvince(wxUserInfo.getProvince());
        if (null != wxUserInfo.getCountry() && 0 < wxUserInfo.getCountry().trim().length())
            u.setCountry(wxUserInfo.getCountry());
        if (null != wxUserInfo.getGender())
            u.setGender(wxUserInfo.getGender());
        // 判断有无密文信息，补充手机号
        if (null != wxUserInfo.getEncData()
                && 0 < wxUserInfo.getEncData().trim().length()
                && null != wxUserInfo.getIv()
                && 0 < wxUserInfo.getIv().trim().length()) {
            String encData = wxUserInfo.getEncData().trim();
            String iv = wxUserInfo.getIv().trim();
            String session_key = ToolsUtil.desencrypt(u.getPsw());
            log.info("微信用户开始对用户基本信息-手机号补充，encData：{}，iv：{}，sessionKey：{} -------------- START", encData, iv, session_key);
            byte[] encrypData = ToolsUtil.decodeBase64(encData);
            byte[] ivData = ToolsUtil.decodeBase64(iv);
            byte[] sessionKey = ToolsUtil.decodeBase64(session_key);
            encData = new String(ToolsUtil.asedecrypt(sessionKey, ivData, encrypData), "UTF-8");
            log.info("微信用户开始对用户基本信息-手机号补充，encData：{}，iv：{}，sessionKey：{} -------------- END", encData, iv, session_key);
            WxEncData wxEncData = JacksonUtil.readValue(encData, WxEncData.class);
            if (null != wxEncData && null != wxEncData.getPurePhoneNumber() && 0 < wxEncData.getPhoneNumber().trim().length()) {
                u.setPhone(wxEncData.getPhoneNumber().trim());
            }
        }
        userService.update(u);
        return new ResultMsg("200", messages.getMessage("success", null, "SUCCESS", null), new Date());
    }

    @ApiOperation(value="发型师端获取关注他的用户信息列表", notes="此接口只允许管理员和发型师调用，返回关注他的用户列表信息")
    @ApiImplicitParam(name = "pageConf", value = "分页信息实体", required = true, dataType = "PageConf")
    @PreAuthorize("hasAnyRole('ADMIN', 'HAIRDRE')")
    @RequestMapping(value="/at/list", method=RequestMethod.POST)
    public MapList<UserInfo> atList(@RequestBody PageConf pageConf) throws RequestParamterException {
        XmUser xmUser = (XmUser) SecurityContextHolder.getContext()
                .getAuthentication().getPrincipal();
        if (0 == xmUser.getHairdresserid()) {
            throw new RequestParamterException("当前用户非发型师用户，查无发型师信息");
        }
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("hairdresserid", xmUser.getHairdresserid());
        Page<UserInfo> u = (Page<UserInfo>) userService.findAllByPage(pageConf, map);
        Long allCount = u.getTotalElements();
        return new MapList<UserInfo>(allCount, u.getContent());
    }
    
}
